class MapInstance::CreatureSpawnObject : public AoiActor
{
public:
	CreatureSpawnObject(MapInstance* pMapInstance, const CreatureSpawn* pSpawn)
		: AoiActor(OTHER, /*1 << VACUOUS | */1 << SPAWN)
		, m_pMapInstance(pMapInstance), m_pSpawn(pSpawn), m_isSpawning(false)
	{}
private:
	virtual void OnSpawn() {
		if (!m_isSpawning) {
			m_isSpawning = true;
			m_pMapInstance->AddEvent([=]() {
				m_pMapInstance->SpawnCreature(m_pSpawn);
				m_pMapInstance->RemoveSpawnObject(this);
			});
		}
	}
	MapInstance* const m_pMapInstance;
	const CreatureSpawn* const m_pSpawn;
	bool m_isSpawning;
};

class MapInstance::StaticObjectSpawnObject : public AoiActor
{
public:
	StaticObjectSpawnObject(MapInstance* pMapInstance, const StaticObjectSpawn* pSpawn)
		: AoiActor(OTHER, /*1 << VACUOUS | */1 << SPAWN)
		, m_pMapInstance(pMapInstance), m_pSpawn(pSpawn), m_isSpawning(false)
	{}
private:
	virtual void OnSpawn() {
		if (!m_isSpawning) {
			m_isSpawning = true;
			m_pMapInstance->AddEvent([=]() {
				m_pMapInstance->SpawnStaticObject(m_pSpawn);
				m_pMapInstance->RemoveSpawnObject(this);
			});
		}
	}
	MapInstance* const m_pMapInstance;
	const StaticObjectSpawn* const m_pSpawn;
	bool m_isSpawning;
};

class Creature::EtherealObject : public AoiActor
{
public:
	EtherealObject(Creature* pOwner, float radius, int flags)
		: AoiActor(OTHER, 1 << PRECISE | 1 << VACUOUS)
		, m_pOwner(pOwner), m_flags(flags)
	{ AoiActor::SetRadius(radius); }
private:
	virtual bool TestInteresting(AoiActor *actor) const {
		auto pLObj = static_cast<LocatableObject*>(actor);
		if (pLObj->IsKindOf(TYPE_UNIT)) {
			if ((m_flags & ETHEREAL_PLAYER_INTERESTING) != 0 &&
				pLObj->IsKindOf(TYPE_PLAYER)) {
				return true;
			}
			if ((m_flags & ETHEREAL_CREATURE_INTERESTING) != 0 &&
				pLObj->IsKindOf(TYPE_CREATURE)) {
				return true;
			}
		}
		return false;
	}
	virtual void OnAddMarker(AoiActor *actor) {
		auto pUnit = static_cast<Unit*>(actor);
		m_pOwner->ObjectHookEvent_OnEObjUnitEnter(this, pUnit);
	}
	virtual void OnRemoveMarker(AoiActor *actor) {
		auto pUnit = static_cast<Unit*>(actor);
		m_pOwner->ObjectHookEvent_OnEObjUnitLeave(this, pUnit);
	}
	Creature* const m_pOwner;
	int const m_flags;
};
